Skip to content

Start nspawn workers after reboot on RHEL and recover stopped workers - #437

Open
hbc (bcho) with Copilot wants to merge 13 commits into
mainfrom
copilot/fix-machines-target-issue
Open

hbc (bcho) with Copilot wants to merge 13 commits into
mainfrom
copilot/fix-machines-target-issue

Conversation

Copilot AI commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Summary

RHEL presets leave machines.target disabled, preventing workers from starting after reboot. The daemon still reported success because it checked persisted settings, not worker liveness.

  • Boot startup: Add Wants=machines.target to host and container daemon units.
  • Preflight: Warn on disabled targets; fail on missing or masked targets.
  • Worker health: Verify the active worker before reporting success, restart it without repaving if stopped, and return reconcile errors when inspection or recovery fails.

Validation

Full test suite, affected-package race tests, vet, documentation checks, build, and CLI smoke test passed. CodeQL and secret scans were clean.

golangci-lint was unavailable; live RHEL reboot testing remains outstanding.

Changelog

  • I added a user/operator-facing entry under Unreleased in CHANGELOG.md, or this change does not require a changelog entry.

Co-authored-by: bcho <1975118+bcho@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix machines.target disabled issue on RHEL hosts Start nspawn workers after reboot on RHEL and recover stopped workers Nov 10, 2026
Copilot AI requested a review from hbc (bcho) November 10, 2026 18:20
Comment thread pkg/daemon/repave_reconciler.go Resolved
Co-authored-by: bcho <1975118+bcho@users.noreply.github.com>
Comment thread pkg/daemon/preflight.go Resolved
Co-authored-by: bcho <1975118+bcho@users.noreply.github.com>
Copilot AI deployed to e2e-testing November 10, 2026 19:31 Active
@plombardi89
Philip Lombardi (plombardi89) marked this pull request as ready for review November 10, 2026 20:18
Copilot AI balanced review requested due to automatic review settings November 10, 2026 20:18

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Worker failures can go undetected and unrecovered, while the new preflight check blocks online bootstrap before required packages can be installed.

2 open issues
What changed in this PR

This PR addresses the reboot-startup portion of #436 by making the Flex Node daemon request machines.target, allowing enabled nspawn workers to start even when RHEL presets disable the target.

Changes:

  • Add machines.target dependencies to host and container daemon units.
  • Register a preflight check for target availability and enablement.
  • Add checker tests, update service snapshots, and document preflight behavior.
File Description
pkg/​daemon/​testdata/​aks-flex-node-agent.service.golden Update the expected host-unit dependency.
pkg/​daemon/​testdata/​aks-flex-node-agent-arc.service.golden Update the expected Arc-enabled unit dependency.
pkg/​daemon/​preflight.go Add target-state validation.
pkg/​daemon/​preflight_test.go Test target states and daemon-unit dependencies.
pkg/​daemon/​assets/​aks-flex-node-agent.service Request worker startup through machines.target.
pkg/​daemon/​assets/​aks-flex-node-agent-container.service Add the same dependency for container deployments.
pkg/​cmd/​preflight/​preflight.go Register the new preflight check.
docs/​usage/​operations.md Explain target-check errors and warnings.

Review effort: Balanced

Comment thread pkg/daemon/preflight.go Resolved

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this. The boot fix itself works. Requesting changes for the preflight check and some housekeeping.

Blocking

  1. The machines-target check fails preflight on a fresh host where systemd-container isn't installed yet, although bootstrap installs it and unbounded's own checks only warn about it. Inline on pkg/daemon/preflight.go:37, with a reproducer on RHEL 9.8.
  2. Housekeeping before merge:
    • The description is out of date. It still lists the "Worker health" changes that 695b06b removed.
    • Fixes #436 will close the issue, but only half of it is fixed. The issue's second request (the agent noticing a stopped worker instead of reporting success for three days) was dropped. Please use Refs #436 and open a follow-up issue, or note on #436 that this part won't be done.
    • No CHANGELOG.md entry. There's an [Unreleased] section, and this change is user-facing: a fix (workers now start after reboot on RHEL) and a new preflight check.

Verified: Wants=machines.target. I tested it on systemd 252 (Rocky Linux 9.8, the same systemd as the RHEL 9.8 hosts in #436):

  • The worker was the real systemd-nspawn@.service, with only its process replaced by sleep.
  • The agent unit was the actual golden unit from main or from this PR, again with only ExecStart replaced.
  • machines.target was disabled and systemd-nspawn@kube1.service was enabled, as on the reporter's hosts.
  • Each scenario was a reboot.
Scenario machines.target Worker Agent
Agent unit from main inactive never started (reproduces #436) active
Agent unit from this PR active active active, without waiting for the worker
PR's container-variant unit, containerd start fails active active not started (dependency failed)
Worker disabled and stopped on purpose, as unbounded does when it stops a machine active stays stopped active

The upgrade path also heals hosts that are already stuck. Writing the new unit and running daemon-reload alone starts nothing, but the agent restart that follows an upgrade starts machines.target and the stopped worker. Stopping the agent doesn't stop either of them.

After=machines.target: no change needed. Unbounded's own daemon unit has After= as well as Wants=. Adding it here would hold the agent until the worker's start finishes; I tested that, and a worker whose start fails doesn't block the agent. A start that hangs would hold it for up to the worker's start timeout, 90 seconds by default for the Type=notify nspawn unit. I found nothing in pkg/daemon that assumes the worker is up at startup, and the worker's pre-start/post-start hooks don't depend on the agent unit. So Wants= alone is the better choice here.

The remaining gap is a real reboot of a real RHEL host with a real nspawn worker, which the PR description already lists as outstanding.

Comment thread pkg/daemon/preflight.go Resolved
@bcho

Copy link
Copy Markdown
Member

Copilot address pr comments

Co-authored-by: bcho <1975118+bcho@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Preflight incorrectly rejects valid linked systemd targets, and runtime-only links also need a persistence warning.

2 open issues
1 resolved since last review

Review effort: Balanced

Comment thread pkg/daemon/preflight.go Resolved
Comment thread CHANGELOG.md Resolved
Co-authored-by: bcho <1975118+bcho@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 11, 2026 21:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Human assessment is needed to weigh the operational impact of limited preflight failure diagnostics.

1 open issue
1 resolved since last review

Review effort: Balanced

Co-authored-by: bcho <1975118+bcho@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 11, 2026 21:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Human assessment is needed to weigh an unpublished low-severity concern about diagnosing systemd inspection failures.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@bcho

Copy link
Copy Markdown
Member

Copilot resolve conflicts

…target-issue

# Conflicts:
#	CHANGELOG.md

Co-authored-by: bcho <1975118+bcho@users.noreply.github.com>
Copilot AI balanced review requested due to automatic review settings November 11, 2026 21:27

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The preflight result omits the underlying error, leaving operators without the cause when systemctl cannot be started.

1 open issue

Review effort: Balanced

Comment thread pkg/daemon/preflight.go Resolved

Copilot AI commented Nov 11, 2026

Copy link
Copy Markdown
Contributor Author

Copilot resolve conflicts

Resolved the changelog conflict by merging main in f05131a. Targeted Go tests and documentation checks passed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. The preflight fix is verified (details in the resolved thread), and the boot fix holds up on a real RHEL host (below).

Before merging, please update the PR's title and description. They still describe work that 695b06b removed:

  • Title: drop "and recover stopped workers", for example "Start nspawn workers after reboot on RHEL".
  • Body:
    • remove the "Worker health" bullet
    • update the "Preflight" bullet to the online/offline/containerized behavior
    • replace "live RHEL reboot testing remains outstanding" (results below)
    • check the changelog box
  • Use Refs #436 instead of Fixes #436, and open a follow-up issue for the second request (the agent noticing a stopped worker). The test below reproduced it: with the worker down and the node NotReady, the agent kept logging decision=ReportSucceeded reason="goal state is applied". Merging with Fixes would close the issue with that still open.

Real RHEL host test. Setup:

  • an Azure VM from RedHat:RHEL:9_8-gen2, joined to a new AKS cluster with the repo's e2e token-join scripts
  • the boot fix from this PR (the unit files are unchanged since 69f1cc6)
  • machines.target disabled by the RHEL preset, with systemd-nspawn@kube1 enabled under it, as in #436

Each row is a reboot unless noted:

Test machines.target Worker Node
This PR's unit active (still disabled) started; its kubelet was running 13 s after boot Ready
Pre-PR Wants= line restored inactive never started NotReady; the agent kept reporting ReportSucceeded
Agent restart, as after an upgrade, with the worker down (no reboot) started started Ready again
The unit as the agent rewrote it at startup active started Ready

Also from that host:

  • Wants= alone is enough. The worker was active 3 s before the agent even without After=machines.target, because the agent also waits for network-online.target.
  • The project's own e2e token-join flow hits the old preflight error on RHEL. It installs host packages only with apt-get, so it reached preflight without systemd-container and failed on machines-target. With the current head that's a warning.

Separate from this PR: the agent crash-loops on RHEL with SELinux enforcing. Enforcing is the default on Azure's RHEL images, so I set the test VM to permissive to get through the test.

  • The error: initialize agent binary layout: initialize daemon compatibility symlink: symlink /opt/unbounded/agent/lib/aks-flex-node/aks-flex-node-current /opt/unbounded/agent/bin/.aks-flex-node…/tmp.symlink: permission denied
  • A/B test: enforcing fails, permissive works.
  • Context: the agent runs as init_t, and its binary under /opt/unbounded/agent/lib is labeled lib_t. No AVC is logged, even with dontaudit rules disabled.
  • Suggestion: this probably deserves its own issue.

This branch is being deployed

1 in progress deployment
e2e-testing — f05131ae Deployed Nov 11, 2026 by Copilot via E2E Tests #1324
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] machines.target disabled on RHEL hosts

4 participants